﻿using cn.Ysserver;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using org.eclipse.paho.client.mqttv3.@internal;
using org.eclipse.paho.client.mqttv3;
using org.eclipse.paho.client.mqttv3.logging;
using org.eclipse.paho.client.mqttv3.persist;
using org.eclipse.paho.client.mqttv3.util;
using cn.Ysserver.entity;
using cn.Ysserver.impl;
using cn.Ysserver.Interface;
using cn.Ysserver.utils;
using cn.ys.ysdatatransfer.business;
using System.Collections;
using System.Net.NetworkInformation;

namespace Ys4GClient
{
    public partial class main : Form
    {
        private static main Instance;
        private  YsCloudClient mYsCloudClient;
        private Ys_callback mYsCloudClientCallback;
        private String[] mDeviceSn;
        private String rsa_private_key = @"<RSAKeyValue><Modulus>uOqxIXLFeDL9n1u+yo9LNzRxoV6U04YYenAXIbJ/CAO6wbjBaf9m6Sw9mJXoJr3IA9w6Plw1wgLrBLP0ngW7cFSQVbT/p2zx5NhDLTZ6NeHV+lZNLSFL6niUvDCBIyrims8VG7+FLXqrjBa0YOny5MhCdP2K67lNCBUwlDr+nLs=</Modulus><Exponent>AQAB</Exponent><P>xyscDUZcb7beXz60mUSMtTOuzxSCmqqXlgP1bhGr5RCBSADIeZoy8+k2ILfzTDorlwd9pqSbFBf/W4rVGp6d4w==</P><Q>7a6Gx+flU3M2YJFQ+8qVD08j8vjcoSG3JaSfUB5Z3WE1ZPug36LSjIgZ4EsZQ9mjreVgYkxylkhAwiDfSHG9SQ==</Q><DP>BoM7XJfDaAfDx7uGLkjWjQpOmgjiqGoRoN8qRFohk9DxWUhlRcysA9vJYFKDiyePy1V8X1mclJCgUf79Luym3w==</DP><DQ>vEaFyZDuXd5j8rbp2aqtzQS5y1xLGPCmLZFsCYEhWnYIX8fbtYs7Ecs2BDA5AUBDohqS8Qrxsg3mDmEPvkkq0Q==</DQ><InverseQ>stTU8PLYXfq391Er67p5yfYdsEdnXQBaQESIWAnxUE2QmqRZ00rX3MnbhkvcMlFxfoOrfOWJWTEQQKiTtHQs5g==</InverseQ><D>AZpZP7VPjaU+VU3VaJjD3KN8+gGJFCQ+CtLC+pwYBskwtMHu5/vxtVmnlx0TgqrGhac4iBGUXIox+ZO8b1FgB63o+1ihdAefG7siXpsL5adO85hjuQs1XIpC63Fm2WMi8yYNnS8QB0v7G+CKdTtWDEkfpyUBB74Kb9bihEZ1AHE=</D></RSAKeyValue>";

        public main()
        {
            Instance = this;
            mYsCloudClientCallback = new Ys_callback();
            mYsCloudClient = Program.ysCloudClient;
            mYsCloudClient.setUsrCloudMqttCallback(mYsCloudClientCallback);
            InitializeComponent();
            this.Resize += Form1_Resize;
        }

        private class Ys_callback : YsCloudMqttCallbackAdapter
        {
            override
            public void onConnectAck(int returnCode, String description)
            {
                System.Console.WriteLine("onConnectAck:" + returnCode + description);
                if (returnCode == 2) 
                {
                    Instance.udate_state(Instance.connect_state, "连接成功", Color.Lime); 
                    if (Instance.mDeviceSn != null) 
                    {
                        for (int i = 0; i < Instance.mDeviceSn.Length; i++) 
                        {
                            try {
                                String topic_sub = map_client_key[Instance.mDeviceSn[i]].topic_sub;
                                Instance.doSubscribeForTopic(topic_sub);
                            } 
                            catch (Exception e) 
                            {
                                // TODO: handle exception
                                System.Console.WriteLine("reconect:"+e.ToString());
                            }
                        }
                    }
                } 
                else 
                {
                    Instance.udate_state(Instance.connect_state, "连接断开", Color.Red); ;
                }
            }

            override
            public void onSubscribeAck(int messageId, String clientId, String topics, int returnCode)
            {
                topics = topics.Substring(1, topics.Length - 2);
                if (returnCode == 0) 
                {
                    // 找出键值对的对象
                    Client_struct this_client = null;
                    String client_key;
                    //遍历value
                    foreach (Client_struct value in map_client_key.Values) 
                    {
                        if (string.Equals(value.topic_sub, topics)) 
                        {
                            this_client = value;
                            client_key = value.client_id;
                            break;
                        }
                    }
                    if (this_client == null) 
                    {
                        System.Console.WriteLine("连接设备" + this_client.client_id + "成功" + " 但是查找字典时失败，请检查是否正常");
                        return;
                    }
                    System.Console.WriteLine("连接设备" + this_client.client_id + "成功");
                    if (this_client.tcpService != null)
                    {
                        return;
                    }
                    this_client.tcpService = new TcpService( new Tcpinterface(), this_client.tcp_port, this_client.topic_pub);
                    if (!PortInUse(this_client.tcp_port))
                    {
                        new java.lang.Thread(this_client.tcpService).start();
                        for (int i = 0; i < Instance.mDeviceSn.Length; i++)
                        {
                            if (this_client.tcp_port == (int)Instance.dataGridView.Rows[i].Cells[2].Value)
                            {
                                Instance.dataGridView.Rows[i].Cells[2].Style.ForeColor = Color.Green;
                                Instance.dataGridView.Rows[i].Cells[5].Value = "服务已启动";
                                break;
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < Instance.mDeviceSn.Length; i++)
                        {
                            if (this_client.tcp_port == (int)Instance.dataGridView.Rows[i].Cells[2].Value)
                            {
                                Instance.dataGridView.Rows[i].Cells[2].Style.ForeColor = Color.Red;
                                Instance.dataGridView.Rows[i].Cells[5].Value = "端口被占用";
                                break;
                            }
                        }

                    }
                }
            }

            override
            public void onReceiveParsedEvent(int messageId, String topic, String jsonData)
            {

            }

            override
            public void onDisSubscribeAck(int messageId, String clientId, String topics, int returnCode)
            {
        
            }

            override
            public void onPublishDataAck(int messageId, String topic, Boolean isSuccess)
            {

            }

            override
            public void onPublishDataResult(int messageId, String topic)
            {

            }

            override
            public void onReceiveEvent(int messageId, String topic, byte[] data)
            {
                //遍历value
                foreach (Client_struct value in map_client_key.Values)
                {
                    if (string.Equals(value.topic_sub, topic))
                    {
                        try
                        {
                            value.tcpService.send(data);
                        }
                        catch (Exception e) {
                            // TODO: handle exception
                            System.Console.WriteLine("onReceiveEvent:" + e.ToString());
                        }
                        break;
                    }
                }
             
            }
        }
        internal static bool PortInUse(int port)
         {
         bool inUse = false;
   
         IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
         IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
   
   
         foreach (IPEndPoint endPoint in ipEndPoints)
         {
         if (endPoint.Port == port)
         {
         inUse = true;
         break;
         }
         }
         return inUse;
       }


        private void udate_state(Label label, String text, Color color)
        {
            if (!Instance.IsDisposed)
            {
                Instance.BeginInvoke(
                    (MethodInvoker)
                        delegate
                        {
                            label.Text = text;
                            if (color != null)
                            {
                                label.BackColor = color;
                            }
                        }
                    );
            }
        }

        //解密
        private string Decrypt(string ciphertext)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(rsa_private_key);
                byte[] encryptdata = Convert.FromBase64String(ciphertext);
                byte[] decryptdata = rsa.Decrypt(encryptdata, false);
                return Encoding.Default.GetString(decryptdata);
            }
        }

        //采用字典存储 clientid 与 Client_struct 的对应
      //  private static Dictionary<String, TcpService> map_key_tcpservice = new Dictionary<string, TcpService>;
        private static Dictionary<String, Client_struct>  map_client_key = new Dictionary<String, Client_struct>();
        private class Tcpinterface : TcpDataInterface
        {
            public void onDataReceived(byte[] barr, string str)
            {
                Instance.publishForTopic(str, barr);
            }

            public void onDataSent(byte[] barr)
            {

            }
        }

        private class Client_struct
        {

            public String client_id;
            public String topic_sub;
            public String topic_pub;
            public String topic_devinfo;
            public int tcp_port;
            public TcpService tcpService;

            public Client_struct(String client_id, int tcp_port)
            {
                this.client_id = client_id;
                this.topic_sub = "$USR/DevTx/" + client_id;
                this.topic_pub = "$USR/DevRx/" + client_id;
                this.topic_devinfo = "$USR/DevInfo/" + client_id;
                this.tcp_port = tcp_port;
            }
        }

        private Boolean is_mqtt_online()
        {
            if (mYsCloudClient == null)
            {
                return false;
            }
            else
            {
                try
                {
                    return mYsCloudClient.is_mqtt_connected();
                }
                catch (java.lang.NullPointerException e)
                {
                    e.printStackTrace();
                }
                catch (java.lang.RuntimeException e)
                {
                    e.printStackTrace();
                }
            }
            return false;
        }

        private void doSubscribeForTopic(String topic)
        {
            try
            {
                mYsCloudClient.setUsrCloudMqttCallback(mYsCloudClientCallback);
                mYsCloudClient.SubscribeForTopic(topic);
            }
            catch (Exception e)
            {
                System.Console.WriteLine("doSubscribeForTopic" + e.ToString());
            }
        }


        private void publishForTopic(String topic, byte[] data)
        {
            if (is_mqtt_online())
            {
                try
                {
                    mYsCloudClient.setUsrCloudMqttCallback(mYsCloudClientCallback);
                    mYsCloudClient.publishForDevTopic(topic, data);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("publishForTopic"+e.ToString());
                }
            }
        }

        public static string getLocalIP()
        {
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    //从IP地址列表中筛选出IPv4类型的IP地址
                    //AddressFamily.InterNetwork表示此IP为IPv4,
                    //AddressFamily.InterNetworkV6表示此地址为IPv6类型
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        return IpEntry.AddressList[i].ToString();
                    }
                }
                return "";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Hide();
            login.mInstance.Show();
        }

        private string readKeyconfigPathFromXML()
        {
            string path = Environment.CurrentDirectory + "\\KeyconfigPath.xml";
            if (!File.Exists(path))
            {
                XmlTextWriter writeXml = new XmlTextWriter("KeyconfigPath.xml", Encoding.UTF8);
                writeXml.WriteStartDocument(false);
                writeXml.WriteStartElement("KEYCONFIG_PATH");
                writeXml.WriteElementString("KeyconfigPath", "");
                writeXml.WriteEndElement();
                writeXml.Flush();
                writeXml.Close();
            }
            //创建一个XmlTextReader对象，读取XML数据
            XmlTextReader xmlReader = new XmlTextReader("KeyconfigPath.xml");
            string keyconfig_path = "";
            while (xmlReader.Read())
            {
                if (true == xmlReader.Name.Equals("KeyconfigPath"))
                {
                    keyconfig_path = xmlReader.ReadString().Trim();
                }
            }
            xmlReader.Close();
            return keyconfig_path;
        }

        private void saveKeyconfigPathToXml(string path)
        {
            XmlTextReader xmlReader = new XmlTextReader("KeyconfigPath.xml");
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("KeyconfigPath.xml");
            XmlNode path_node = xmlDoc.GetElementsByTagName("KeyconfigPath").Item(0);
            path_node.InnerText = path;
            xmlDoc.Save("KeyconfigPath.xml");
        }

        private void Main_Load(object sender, EventArgs e)
        {
            ip_addr.Text = getLocalIP();
            string path = readKeyconfigPathFromXML();
            if (File.Exists(path))
            {
                loadKeyconfig(path);
            }
        }

        void Form1_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Visible = false;
                this.notifyIcon1.Visible = true;
            }
        }

        private void btn_key_Click(object sender, EventArgs e)
        {
            //遍历value
            foreach (Client_struct value in map_client_key.Values)
            {
                try
                {
                    value.tcpService.stopservice();
                }
                catch
                {
                }
            }
            map_client_key.Clear();
            OpenFileDialog dialog = new OpenFileDialog();
            //该值确定是否可以选择多个文件
            dialog.Multiselect = false;
            dialog.Title = "请选择keyconfig文件";
            dialog.Filter = "keyconfig|keyconfig";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string file = dialog.FileName;
                loadKeyconfig(file);
            }
        }

        private void loadKeyconfig(string file)
        {
            StreamReader reader = new StreamReader(file, Encoding.Default);
            string content = File.ReadAllText(file);
            if (content.EndsWith("\r\n"))
            {
                content = content.Substring(0, content.Length - 2);
            }
            if (content != null)
            {
                saveKeyconfigPathToXml(file);
                string[] strs = content.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                mDeviceSn = new string[strs.Length];
                dataGridView.Rows.Clear();
                for (int i = 0; i < strs.Length; i++)
                {
                    mDeviceSn[i] = Decrypt(strs[i]);
                    int index = dataGridView.Rows.Add();
                    dataGridView.Rows[index].Cells[0].Value = index + 1;
                    dataGridView.Rows[index].Cells[1].Value = mDeviceSn[i];
                    int port = int.Parse(start_port.Text) + i;
                    dataGridView.Rows[index].Cells[2].Value = port;
                    dataGridView.Rows[index].Cells[5].Value = "正在连接设备..";
                    Client_struct client_Struct = new Client_struct(mDeviceSn[i], port);
                    map_client_key.Add(mDeviceSn[i], client_Struct);
                    doSubscribeForTopic(client_Struct.topic_sub);
                }
            }
        }
 
        private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridView.Columns[e.ColumnIndex].Name == "col_clear")
            {
                if (e.RowIndex == -1)
                {
                    foreach (Client_struct value in map_client_key.Values)
                    {
                        value.tcpService.data_get = 0;
                        value.tcpService.data_send = 0;
                    }
                    return;
                }
                foreach (Client_struct value in map_client_key.Values)
                {
                    if (value.tcp_port == (int)dataGridView.Rows[e.RowIndex].Cells[2].Value)
                    {
                        value.tcpService.data_get = 0;
                        value.tcpService.data_send = 0;
                        break;
                    }

                }
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
            this.Show();
        }

        private void notifymenu_Opening(object sender, CancelEventArgs e)
        {

        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult dr;
            dr = MessageBox.Show("确定要退出吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (dr == DialogResult.OK)
            {
                foreach (Client_struct value in map_client_key.Values)
                {
                    try
                    {
                        value.tcpService.stopservice();
                    }
                    catch
                    { }
                }
                map_client_key.Clear();
                mYsCloudClient.DisConnectUnCheck();
                mYsCloudClient = null;
                //遍历value
                this.Dispose(true);
                //通知垃圾回收机制不再调用终结器（析构器）
                GC.SuppressFinalize(this);
                System.Environment.Exit(System.Environment.ExitCode);
                this.Close();
                e.Cancel = false; ;
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void 显示主界面ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
            this.Show();
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("是否确认退出程序？", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                // 关闭所有的线程
                foreach (Client_struct value in map_client_key.Values)
                {
                    try
                    {
                        value.tcpService.stopservice();
                    }
                    catch
                    { }
                }
                map_client_key.Clear();
                mYsCloudClient.DisConnectUnCheck();
                mYsCloudClient = null;
                System.Environment.Exit(System.Environment.ExitCode);
                this.Dispose(true);
                //通知垃圾回收机制不再调用终结器（析构器）
                GC.SuppressFinalize(this);
                this.Close();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                foreach (Client_struct value in map_client_key.Values)
                {
                    for (int i = 0; i < dataGridView.Rows.Count; i++)
                    {
                        if (value.tcp_port == (int)dataGridView.Rows[i].Cells[2].Value)
                        {
                            dataGridView.Rows[i].Cells[3].Value = value.tcpService.data_get;
                            dataGridView.Rows[i].Cells[4].Value = value.tcpService.data_send;
                            if (value.tcpService.socketList.size() > 0)
                            {
                                Instance.dataGridView.Rows[i].Cells[5].Style.ForeColor = Color.Green;
                                dataGridView.Rows[i].Cells[5].Value = "MP已连接";
                            }
                            else
                            {
                                if (!dataGridView.Rows[i].Cells[5].Value.Equals("端口被占用"))
                                {
                                    Instance.dataGridView.Rows[i].Cells[5].Style.ForeColor = Color.Blue;
                                    dataGridView.Rows[i].Cells[5].Value = "服务已启动";
                                }
                                else
                                {
                                    Instance.dataGridView.Rows[i].Cells[5].Style.ForeColor = Color.Gray;
                                }

                              
                            }
                            break;
                        }
                    }
                }
            }
            catch (Exception )
            {
                //TODO: handle exception
                //System.Console.WriteLine(e.ToString());
            }
        }
    }
}
